package com.view;

import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.FrameLayout;
import android.widget.Scroller;

import com.util.LogUtil;
import com.util.R;

import butterknife.Bind;
import butterknife.ButterKnife;

/**
 * 弹性滑动RecyclerView
 * Created by Administrator on 2016/6/22.
 */
public class ElasticityRecyclerView extends FrameLayout {
    @Bind(R.id.rv_elasticityRecyclerViewCv)
    RecyclerView rv;
    private CustomLinearLayoutManager linearLayoutManager;
    private Context context;
    private Scroller mScroller; //滑动类
    private int touchSlop; //最小滑动距离
    private float elasticity = 0.6f; //阻尼系数,越大下拉越困难


    private boolean isOverPullDowning = false;
    private boolean isOverPullUping = false;
    private float downYInRv; //RecyclerView点击按下的位置
    private float slideDistanceInRv; //RecyclerView中两次滑动的距离差

    public ElasticityRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        initElasticityRecyclerView();
        initRecyclerView();
    }

    private void initElasticityRecyclerView() {
        View view = LayoutInflater.from(context).inflate(R.layout.cv_elasticity_recyclerview, this);
        ButterKnife.bind(view);
        touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        mScroller = new Scroller(context);
    }

    private void initRecyclerView() {
        linearLayoutManager = new CustomLinearLayoutManager(context);
        rv.setLayoutManager(linearLayoutManager);
        rv.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        downYInRv = event.getY();
//                        LogUtil.i("test", "RvACTION_DOWN:"+downYInRv);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        slideDistanceInRv = event.getY() - downYInRv;
                        LogUtil.i("test", slideDistanceInRv);
                        if (Math.abs(slideDistanceInRv) >= touchSlop) { //达到滑动条件
                            if (slideDistanceInRv > 0) { //下拉
                                if(isOverPullUping){
                                    scrollTo(0, 0);
                                    linearLayoutManager.setScrollEnabled(true);
                                    isOverPullUping = false;
                                }

                                if(isEnablePullDown()){ //下拉超出边界
                                    linearLayoutManager.setScrollEnabled(false);
                                    scrollTo(0, (int) -(slideDistanceInRv - slideDistanceInRv * elasticity));
                                    isOverPullDowning = true;
                                }
                            } else { //上拉
                                if(isOverPullDowning){
                                    scrollTo(0, 0);
                                    linearLayoutManager.setScrollEnabled(true);
                                    isOverPullDowning = false;
                                }
                                if(isEnablePullUp()){ //上拉超出边界
                                    linearLayoutManager.setScrollEnabled(false);
                                    scrollTo(0, (int) -(slideDistanceInRv - slideDistanceInRv * elasticity));
                                    isOverPullUping = true;
                                }
                            }

                        }
//                        LogUtil.i("test", "RvACTION_MOVE");
                        break;
                    case MotionEvent.ACTION_UP:
                        linearLayoutManager.setScrollEnabled(true);
                        isOverPullDowning = false;
                        isOverPullUping = false;
                        smoothScrollTo(0);
                        invalidate();
//                        LogUtil.i("test", "RvACTION_UP");
                        break;
                }
                return false;
            }
        });

    }
    public void setRecyclerViewAdapter(RecyclerView.Adapter adapter) {
        rv.setAdapter(adapter);
    }

    private boolean isEnablePullDown() {
        LinearLayoutManager manager = (LinearLayoutManager) rv.getLayoutManager();
        int firstVisible = manager.findFirstVisibleItemPosition();
        if (manager.getItemCount() == 0) //没有数据时可以下拉
            return true;
        return firstVisible == 0 && manager.getChildAt(0).getTop() == 0;
    }

    private boolean isEnablePullUp() {
        LinearLayoutManager manager = (LinearLayoutManager) rv.getLayoutManager();
        int lastVisible = manager.findLastVisibleItemPosition();
        int totalCount = manager.getItemCount();
        if (totalCount == 0) //没有数据时不可上拉
            return false;
        int bottom = manager.findViewByPosition(lastVisible).getBottom();
        int decorHeight = manager.getBottomDecorationHeight(rv.getChildAt(0));
        return totalCount == lastVisible + 1 && bottom + decorHeight <= getMeasuredHeight();
    }

    private void smoothScrollTo(int destY) {
        int scrollY = getScrollY();
        int deltaY = destY - scrollY;
        mScroller.startScroll(0, scrollY, 0, deltaY, 500);
        invalidate();

    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(0, mScroller.getCurrY());
            invalidate();
        }
    }
}
class CustomLinearLayoutManager extends LinearLayoutManager {
    private boolean isScrollEnabled = true;

    public CustomLinearLayoutManager(Context context) {
        super(context);
        setOrientation(LinearLayoutManager.VERTICAL);
    }

    public void setScrollEnabled(boolean flag) {
        this.isScrollEnabled = flag;
    }

    @Override
    public boolean canScrollVertically() {
        //Similarly you can customize "canScrollHorizontally()" for managing horizontal scroll
        return isScrollEnabled && super.canScrollVertically();
    }
}

